﻿using System;
using System.Collections.Generic;
using Brjnk.Maps;
using MapsTest.TestClasses;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MapsTest
{
    [TestClass()]
    public class MultiTimerTest
    {
        private TestContext testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes

        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //

        #endregion Additional test attributes

        [TestMethod()]
        public void MultiTimerTest1()
        {
            calledActions.Clear();
            var provider = new TestTimingProvider();
            DefaultTimingProvider.SetDefaultTimingProvider(provider);
            MultiTimer target = new MultiTimer();
            target.Add(new TestScheduledAction(callAction, "A"), provider.GetTime().AddSeconds(2));
            target.Add(new TestScheduledAction(callAction, "B"), provider.GetTime().AddSeconds(5));
            var toChange = new TestScheduledAction(callAction, "D");
            target.Add(toChange, provider.GetTime().AddSeconds(2));
            var toDel = new TestScheduledAction(callAction, "XXX");
            target.Add(toDel, provider.GetTime().AddSeconds(1));
            target.Remove(toDel);
            //-------
            //1500
            provider.Move(1500);

            target.Update(toChange, provider.GetTime().AddSeconds(10));
            Assert.AreEqual(0, calledActions.Count);
            //-------
            //2000
            provider.Move(500);

            Assert.AreEqual(1, calledActions.Count);
            Assert.AreEqual("A", calledActions[0]);
            calledActions.Clear();
            //-------
            //5000
            provider.Move(3000);

            Assert.AreEqual(1, calledActions.Count);
            Assert.AreEqual("B", calledActions[0]);
            calledActions.Clear();

            target.Add(new TestScheduledAction(callAction, "C"), provider.GetTime().AddSeconds(5));
            Assert.AreEqual(0, calledActions.Count);
            //-------
            //10 000
            provider.Move(5000);

            Assert.AreEqual(1, calledActions.Count);
            Assert.AreEqual("C", calledActions[0]);
            calledActions.Clear();
            //-------
            //11500
            provider.Move(1500);
            Assert.AreEqual(1, calledActions.Count);
            Assert.AreEqual("D", calledActions[0]);
        }

        private List<string> calledActions = new List<string>();

        private void callAction(string name)
        {
            lock (calledActions)
            {
                calledActions.Add(name);
            }
        }

        //testuje správnou funkci naplánovaných akcí, které vyžadují aktualizaci (UpdateRequired=true)
        [TestMethod()]
        public void MultiTimerUpdateRequiredTest()
        {
            calledActions.Clear();
            var provider = new TestTimingProvider();
            DefaultTimingProvider.SetDefaultTimingProvider(provider);
            MultiTimer target = new MultiTimer();
            target.Add(new TestScheduledAction(callAction, new Action<TimeSpan>(updateAction), new Action<TicksTime, TicksTime>(resetAction), "A") { ProgressRequired = true }, provider.GetTime().AddSeconds(3));
            Assert.IsTrue(from.Ticks == provider.GetTime().Ticks);
            Assert.IsTrue(to.Ticks == provider.GetTime().Ticks + 3000);

            provider.Move(1000);
            Assert.AreEqual(TimeSpan.FromSeconds(2), remaining);
            provider.Move(1000);
            Assert.AreEqual(TimeSpan.FromSeconds(1), remaining);
            provider.Move(1000);
            Assert.AreEqual(TimeSpan.FromSeconds(0), remaining);
        }

        private TimeSpan remaining;

        private void updateAction(TimeSpan remainingTime)
        {
            remaining = remainingTime;
        }

        private TicksTime from; private TicksTime to;

        private void resetAction(TicksTime from, TicksTime to)
        {
            this.from = from;
            this.to = to;
        }
    }
}